//    This file is part of Open WordSearch.
//
//    Open WordSearch is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    Open WordSearch is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Open WordSearch.  If not, see <http://www.gnu.org/licenses/>.
//
//	  Copyright 2009, 2010 Brendan Dahl <dahl.brendan@brendandahl.com>
//	  	http://www.brendandahl.com

package com.dahl.brendan.wordsearch.model;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;

import com.dahl.brendan.wordsearch.Constants;
import com.dahl.brendan.wordsearch.model.dictionary.DictionaryFactory.DictionaryType;

/**
 * 
 * @author Brendan Dahl
 * 
 *         this class holds a single high score and can be used to compare one
 *         high score to another based on the score attribute
 */
public class HighScore implements Comparable<HighScore> {
	final private static int SCORE_MAX = 1000000;
	private Long time;
	private Integer size;
	private String theme;
	private Float themeModifier;
	private Integer wordCount;
	private String name = "";

	private Integer globalRank = -1;
	private Boolean globalHighScore = false;
	private Integer rank = -1;

	private Long score = null;

	/* must restore all variables used in save and restoring app state */
	public HighScore(Bundle bundle) {
    	this.time = bundle.getLong(Constants.KEY_HIGH_SCORE_TIME);
    	this.size = bundle.getInt(Constants.KEY_HIGH_SCORE_SIZE);
    	this.theme = bundle.getString(Constants.KEY_HIGH_SCORE_THEME);
    	this.wordCount = bundle.getInt(Constants.KEY_WORD_COUNT);
    	this.name = bundle.getString(Constants.KEY_HIGH_SCORE_NAME);
    	this.globalRank = bundle.getInt(Constants.KEY_GLOBAL_RANK);
    	this.globalHighScore = bundle.getBoolean(Constants.KEY_GLOBAL_HIGH_SCORE);
    	this.rank = bundle.getInt(Constants.KEY_RANK);
    	this.score = bundle.getLong(Constants.KEY_HIGH_SCORE);
	}

	/* must store all variables used in save and restoring app state */
	public Bundle toBundle() {
		Bundle bundle = new Bundle();
		bundle.putLong(Constants.KEY_HIGH_SCORE_TIME, time);
		bundle.putInt(Constants.KEY_HIGH_SCORE_SIZE, size);
		bundle.putString(Constants.KEY_HIGH_SCORE_THEME, theme);
		bundle.putInt(Constants.KEY_WORD_COUNT, wordCount);
		bundle.putString(Constants.KEY_HIGH_SCORE_NAME, name);
		bundle.putInt(Constants.KEY_GLOBAL_RANK, globalRank);
		bundle.putBoolean(Constants.KEY_GLOBAL_HIGH_SCORE, globalHighScore);
		bundle.putInt(Constants.KEY_RANK, rank);
		bundle.putLong(Constants.KEY_HIGH_SCORE, getScore());
		return bundle;
	}

	/* used to convert from json generated by server api */
	public HighScore(JSONObject json) throws JSONException {
    	this.name = json.getString(Constants.KEY_HIGH_SCORE_NAME);
    	this.score = json.getLong(Constants.KEY_HIGH_SCORE);
    	this.time = json.getLong(Constants.KEY_HIGH_SCORE_TIME);
	}

	/* used to convert to json to passing to server api*/
	public JSONObject toJSON() throws JSONException {
		JSONObject json = new JSONObject();
		json.put(Constants.KEY_HIGH_SCORE_TIME, time);
		json.put(Constants.KEY_HIGH_SCORE_SIZE, size);
		json.put(Constants.KEY_HIGH_SCORE_THEME, theme);
		json.put(Constants.KEY_HIGH_SCORE_NAME, name);
		json.put(Constants.KEY_WORD_COUNT, wordCount);
		return json;
	}

	/* new high scores use this */
	public HighScore(long time, int size, String theme, int wordCount) {
		this.time = time;
		this.size = size;
		this.theme = theme;
		this.wordCount = wordCount;
	}

	/* 1.9 and forward local high scores use this */
	public HighScore(String name, Long score, Long time) {
		this.name = name;
		this.score = score;
		this.time = time;
	}

	/* < 1.9 local high scores use this */ 
	@Deprecated
	public HighScore(String name, long time, int size, float themeModifier) {
		this.name = name;
		this.time = time;
		this.size = size;
		this.themeModifier = themeModifier;
	}

	public int compareTo(HighScore arg0) {
		return arg0.getScore().compareTo(getScore());
	}

	public Boolean isGlobalHighScore() {
		return globalHighScore;
	}

	public Boolean isGlobalError() {
		return globalRank == -1;
	}

	public Integer getGlobalRank() {
		return globalRank;
	}

	public Boolean isHighScore() {
		return rank != -1 && rank < Constants.MAX_TOP_SCORES;
	}

	public String getName() {
		return name;
	}

	public Integer getRank() {
		return rank;
	}

	public Long getScore() {
		if (score == null) {
			score = new Double(getScoreTime() * getScoreTheme() * getScoreSize() * SCORE_MAX).longValue();
		}
		return score;
	}
	
	private double getScoreSize() {
		double score = 100;
		switch (size) {
		default:
		case 7:
			score = 31;
			break;
		case 8:
			score = 54;
			break;
		case 9:
			score = 81;
			break;
		case 10:
			score = 100;
			break;
		case 11:
			score = 115;
			break;
		}
		return score / 100;
	}

	private float getScoreTheme() {
		if (themeModifier == null) {
			float score = 90;
			try {
				DictionaryType dictionaryType = DictionaryType.valueOf(theme);
				if (dictionaryType != null) {
					switch (dictionaryType) {
					case PLACES:
					case ANIMALS:
					case PEOPLE:
					case ADJECTIVES:
					case SAT:
					case KIDS:
					case GERMAN:
						score = 90;
						break;
					case MISC:
						score = 95;
						break;
					case INSANE:
					case NUMBERS:
						score = 100;
						break;
					case CUSTOM:
						score = 80;
						break;
					case RANDOM:
						score = 95;
						break;
					}
				}
			} catch (IllegalArgumentException iae) {
				score = 90;
			}
			themeModifier = score/100;
		}
		return themeModifier;
	}

	private double getScoreTime() {
		return 1 / (time / 1000F);
	}

	public int getSize() {
		return size;
	}

	public String getTheme() {
		return theme;
	}
	
	public long getTime() {
		return time;
	}

//	public void record() {
//		Log.d("SCORE_TIME", Double.toString(getScoreTime()));
//		Log.d("SCORE_THEME", Double.toString(getScoreTheme()));
//		Log.d("SCORE_SIZE", Double.toString(getScoreSize()));
//	}

	public void setGlobalHighScore(Boolean globalHighScore) {
		this.globalHighScore = globalHighScore;
	}

	public void setGlobalRank(Integer globalRank) {
		this.globalRank = globalRank;
	}

	public void setName(String name) {
		name = name.trim();
		if (name.length() > Constants.MAX_NAME_LENGTH) {
			name = name.substring(0, Constants.MAX_NAME_LENGTH-1);
		}
		this.name = name;
	}

	public void setRank(Integer rank) {
		this.rank = rank;
	}

}
